<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/12/5/005
 * Time: 14:12
 */

namespace Platform\System\Tools;

use App\Exceptions\ApiException;
use App\Exceptions\CustomException;
use http\Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Support\Collection;
use Symfony\Component\HttpKernel\Exception\HttpException;

class ResultTool
{
    const CODE_AJAX_SUCCESS = 1;
    const CODE_AJAX_ERROR = 0;
    const CODE_SUCCESS = 200;
    const CODE_TARGET_WRONG = 220;
    const CODE_PARAM_LOST = 221;
    const CODE_PARAM_WRONG = 222;
    const CODE_NO_LOGIN = 401;
    const CODE_NO_RIGHT = 403;
    const CODE_NO_FOUND = 404;

    const PAGINATE = 10;

    static $messageType = [
        self::CODE_AJAX_SUCCESS => '请求成功',
        self::CODE_AJAX_ERROR => '请求失败',
        self::CODE_SUCCESS => '请求成功',
        self::CODE_PARAM_LOST => '参数缺少',
        self::CODE_PARAM_WRONG => '参数错误',
        self::CODE_TARGET_WRONG => '请求对象错误',
        self::CODE_NO_LOGIN => '请先登录',
        self::CODE_NO_RIGHT => '您的权限不足',
        self::CODE_NO_FOUND => '目标不存在',
    ];

    private $code;
    private $message;
    private $data;
    private $meta;
    private $page;
    public function __construct(){
        $this->setCode(self::CODE_SUCCESS);
    }

    public function setCode($code,$message = null){
        $this->code = $code;
        $this->message = $message ? $message :self::$messageType[$code];
        return $this;
    }

    public function setData($data,$transformer = null){
        // fixme 分页的资源用这个
        if (is_object($data) && is_subclass_of($data,AbstractPaginator::class)){
            if (!is_null($transformer) && is_subclass_of($transformer, JsonResource::class)){
                $this->data = new AnonymousResourceCollection($data, $transformer);
            }else{
                $this->data = $data->items();
            }
            return $this;
        }

        // fixme 集合的资源用这个
        if (is_object($data) && is_subclass_of($data,Collection::class)){
            if (!is_null($transformer) && is_subclass_of($transformer, JsonResource::class)){
                $this->data = new AnonymousResourceCollection($data, $transformer);
            }else{
                $this->data = $data;
            }
            return $this;
        }

        // fixme 模型资源用这个
        if (is_object($data) && is_subclass_of($data,Model::class)){
            if (!is_null($transformer) && is_subclass_of($transformer, JsonResource::class)){
                $this->data = new $transformer($data);
            }else{
                $this->data = $data;
            }
            return $this;
        }

        if (is_array($data)){
            $this->data = $data;
            return $this;
        }

        return $this;
    }

    public function setMate($meta){
        $this->meta = $meta;
        return $this;
    }

    public function setPage($data){

        if (!is_object($data) || !is_subclass_of($data,AbstractPaginator::class)){
            return $this;
        }

        $request_data = request()->all();
        unset($request_data['page']);
        $url_data = http_build_query($request_data);

        $this->page = [
            'current_page' => $data->currentPage(),
            'last_page' => $data->lastPage(),
            'total_count' => $data->total(),
            'per_page' => $data->perPage(),
            'next_page_url' => $data->nextPageUrl() ? $data->nextPageUrl().'&'.$url_data : null,
        ];
        return $this;
    }

    public function send(){
        $response = array_filter([
            'code' => $this->code,
            'message' => $this->message,
            'data' => $this->data,
            'meta' => $this->meta,
            'page' => $this->page,
        ]);

        return response()->json($response,self::CODE_SUCCESS);
    }

    public function stop($code,$message = null){
        $message = $message ? $message : self::$messageType[$code];
        throw (new ApiException())->SetErrorMessage($code,$message);
    }
}